package com.tbit.uqbike.service.business.impl;


import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.date.BetweenFormatter;
import cn.hutool.core.date.DateUnit;
import cn.hutool.core.date.DateUtil;
import cn.hutool.crypto.SecureUtil;
import com.alibaba.fastjson.JSONObject;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.github.pagehelper.page.PageMethod;
import com.tbit.common.entity.view.PageResult;
import com.tbit.common.entity.view.Result;
import com.tbit.common.utils.IpUtil;
import com.tbit.common.utils.TbitHttpServiceUtil;
import com.tbit.uqbike.constant.*;
import com.tbit.uqbike.enums.SystemCodeEnum;
import com.tbit.uqbike.manager.exception.BaseException;
import com.tbit.uqbike.object.business.PageData;
import com.tbit.uqbike.object.pojo.*;
import com.tbit.uqbike.object.pojo.vo.*;
import com.tbit.uqbike.object.value.LoginInfo;
import com.tbit.uqbike.object.view.AccountRole;
import com.tbit.uqbike.quartz.FinancialStatisticsQuartz;
import com.tbit.uqbike.service.base.CountryService;
import com.tbit.uqbike.service.base.LoginLogService;
import com.tbit.uqbike.service.base.RedisService;
import com.tbit.uqbike.service.base.TokenService;
import com.tbit.uqbike.service.base.impl.TokenServiceImpl;
import com.tbit.uqbike.service.business.*;
import com.tbit.uqbike.service.rpcservice.PurviewService;
import com.tbit.uqbike.service.rpcservice.SmsAdapterService;
import com.tbit.uqbike.service.rpcservice.SmsService;
import com.tbit.uqbike.webmanager.config.ManagerConfig;
import com.tbit.uqbike.webmanager.controller.BaseController;
import com.tbit.uqbike.webmanager.dao.core.*;
import com.tbit.uqbike.webmanager.sms.ApiAliyunSms;
import com.tbit.uqbike.webmanager.sms.ApiStoreMsgUtils;
import com.tbit.uqbike.webmanager.sms.ClzySmsAuthUtil;
import com.tbit.uqbike.webmanager.sms.InternationalSmsUtil;
import com.tbit.uqbike.webmanager.util.*;
import com.tbit.utils.DateTimeUtil;
import com.tbit.utils.GoogleAuthenticatorUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.function.Function;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

/**
 * @author MyWin
 */
@Service("accountService")
@Slf4j
@RefreshScope
public class AccountServiceImpl implements AccountService {
    @Autowired
    private AccountDao accountDao;
    @Autowired
    private AccountUserDao accountUserDao;
    @Autowired
    private SmsAdapterService smsAdapterService;
    @Autowired
    private TokenService tokenService;
    @Autowired
    private PurviewService purviewService;
    @Autowired
    private CountryService countryService;
    @Autowired
    private LoginLogService loginLogService;
    @Autowired
    private AccountService accountService;
    @Autowired
    private RedisService redisService;
    @Autowired
    private SmsAuthConfigServiceImpl smsAuthConfigService;
    @Autowired
    private HolderAccountBoundService holderAccountBoundService;
    @Autowired
    private FinancialStatisticsQuartz financialStatisticsQuartz;
    @Autowired
    private RoleDao roleDao;
    @Autowired
    private MenuDao menuDao;
    @Autowired
    private SmsAuthConfigDao smsAuthConfigDao;
    @Autowired
    private AccountConfigService accountConfigService;
    @Autowired
    private DispatchConfigService dispatchConfigService;
    @Autowired
    private SupportService supportService;
    @Autowired
    private BatteryMsgService batteryMsgService;
    @Autowired
    private AccountConfigExtDao accountConfigExtDao;
    @Autowired
    private BranConfigService branConfigService;
    @Resource
    private BrandRemoteConfigService brandRemoteConfigService;
    @Autowired
    private BrandRemoteConfigDao brandRemoteConfigDao;
    @Resource
    private TokenServiceImpl tokenServiceImpl;
    @Autowired
    private AccountServiceConfigDao accountServiceConfigDao;
    @Autowired
    private OutAgeDao outAgeDao;
    @Autowired
    private UpKeepConfigService upKeepConfigService;
    @Value("${SEND_LOGIN_CODE_COUNT_BY_DAY:20}")
    private Integer sendLoginCodeCountByDay;


    // 记录登录日志
    private void logLoginInfo(HttpServletRequest request, Account account, AccountUser accountUser) {
        // 登录日志
        String ip = IpUtil.getClientIp(request);
        String userAgent = request.getHeader("User-Agent");
        if (userAgent == null) {
            userAgent = "";
        }
        LoginLog loginLog = new LoginLog();
        loginLog.setType(account.getType());
        loginLog.setId(account.getAccountId());
        loginLog.setIp(ip);
        loginLog.setLoginTime(new Date());
        loginLog.setAgent(userAgent);
        loginLog.setAccountUserId(accountUser.getAccountUserId());

        loginLogService.insert(loginLog);
    }

    @Override
    public void sendCode(Integer brandId, String country, String phone, String type, LoginInfo loginInfo) {
        // 手机号码检测
        countryService.checkPhone(country, phone);
        Map<String, Object> params = new HashMap<>();
        params.put("phone", phone);
        params.put("country", country);
        params.put("brandId", brandId);
        AccountUser accountUser = accountUserDao.getByPhone(params);
        if (null == accountUser) {
            throw new BaseException(SystemCodeEnum.ACCOUNT_NOT_EXIST);
        }
        List<Account> accountList = accountUserDao.getAccountById(accountUser.getAccountUserId());
        if (accountList.isEmpty()) {
            throw new BaseException(SystemCodeEnum.ACCOUNT_NOT_EXIST);
        }
        // 此处默认使用第一个角色发送验证码
        Account account = accountList.get(0);
        SmsService smsService = smsAdapterService.getSmsService(account.getType(), account.getAccountId(), null);
        if (smsService == null) {
            throw new BaseException(SystemCodeEnum.NOT_SUPPORT_SMS_CODE);
        }
        boolean locked = redisService.locked(RedisKeyConstant.format(RedisKeyConstant.SMS_LOGIN_LOCK, phone, type), 60);
        if (locked) {
            throw new BaseException("验证码已下发,请稍后再试");
        }
        String code = Integer.valueOf(SmsService.CODE_RANDOM.nextInt(9000) + 1000).toString();
        chooseSMSTemplate(account, country, phone, code);
        // 记录缓存
        redisService.add(SmsService.getCodeRedisKey(country, phone, type), code, ManagerConfig.LoginCodeSec);
        //限制一个手机号一天只能发送20条短信
        Date date = new Date();
        long secondsUntilMidnight = DateUtil.between(date, DateUtil.endOfDay(date), DateUnit.SECOND) + 1;
        if (redisService.incr(RedisKeyConstant.getSendLoginCodeCountKey(brandId, phone), secondsUntilMidnight) >= sendLoginCodeCountByDay) {
            throw new BaseException("当日发送验证码次数达上限，请明日再试");
        }
    }

    @Override
    public void chooseSMSTemplate(Account account, String country, String phone, String code) {
        /**使用各自品牌的短信模板进行短信发送*/
        Integer brandId = accountDao.getBrandIdByAccountId(account.getAccountId(), account.getType());
        SmsAuthConfig smsConfig = smsAuthConfigService.getByAccountId(brandId);

        Map<String, Integer> map = new HashMap<>();
        map.put("accountId", account.getAccountId());
        map.put("configType", 4);
        BrandRemoteConfig brandRemoteConfig = smsAuthConfigDao.getByConfigType(map);

        if ("86".equals(country)) {
            BrandRemoteConfig brandRemoteConfigDB = smsAuthConfigService.getBrandRemoteConfig(brandId,
                    BrandRemoteConfigConstant.TBIT_CONFIG);
            //优先使用自研短信
            String templateId = smsAuthConfigService.getBrandRemoteConfigValue(brandId,
                    BrandRemoteConfigConstant.SMS_TEMPLATEID);
            boolean send=false;
            if(templateId != null && brandRemoteConfigDB!=null){
                String key = brandRemoteConfigDB.getParamKV();
                String[] strings = key.split("&");
                JSONObject jsonObject = new JSONObject();
                jsonObject.put("code", code);
                boolean result= TbitHttpServiceUtil.sendSms(strings[0].substring(strings[0].indexOf("=") + 1),
                        strings[1].substring(strings[1].indexOf("=") + 1)
                        ,strings[2].substring(strings[2].indexOf("=") + 1),phone,jsonObject.toJSONString(),Integer.valueOf(templateId));
                if(result){
                    send=true;
                }
            }
            //发送失败转旧版发送
            if(!send){
                sendSms(brandId,phone,code,account,brandRemoteConfig,smsConfig);
            }

        } else {
            phone = "00" + country + phone;
            String content = "【Youqudrive Travel】 Your verification code is " + code + ". If you are not operating by yourself, please ignore this message";
            InternationalSmsUtil.send(phone, content);
        }


    }

    private void sendSms(Integer brandId,String phone,String code,Account account,BrandRemoteConfig brandRemoteConfig,SmsAuthConfig smsConfig){
        if (brandId.equals(100019)) {
            /**兼容波思出行账号使用特定短信api发送,暂时不考虑后期兼容*/
            BSCXSmsApi.sendSms(phone, code);
        } else {
            if (account.getType().equals(UserConstant.USER_ADMIN) || null == smsConfig) {
                /**管理员使用泰比特寻程短信发送*/
                ApiStoreMsgUtils.send(phone, code, OperaPswConstant.SMS_SEND_CODE_APPKEY, Integer.valueOf(OperaPswConstant.SMS_SEND_CODE_MODELID));
            } else {
                /**优先考虑创蓝智云短信短信发送*/
                if (brandRemoteConfig != null) {
                    String[] strings = brandRemoteConfig.getParamKV().split("&");
                    String accounts = strings[0].substring(strings[0].indexOf("=") + 1);
                    String password = strings[1].substring(strings[1].indexOf("=") + 1);
                    Account brand = accountDao.getByAccountId(brandId);
                    if (Objects.isNull(brand)){
                        log.info("发送创蓝智云短信失败，{}不存在",  brandId);
                        throw new BaseException("品牌信息不存在");
                    }
                    ClzySmsAuthUtil.sendSms(accounts, password, "【" + brand.getName() + "】您正在申请手机注册,验证码为:" + code + ",5分钟内有效!", phone);
                } else {
                    if (smsConfig.getFrom() == 0) {
                        /**寻程发送短信*/
                        ApiStoreMsgUtils.send(phone, code, smsConfig.getSmsCodeKey(), Integer.valueOf(smsConfig.getSmsModelId()));
                    } else {
                        /**阿里云发送短信*/
                        String[] split = smsConfig.getSmsCodeKey().split(";");
                        if (split.length != 2) {
                            throw new BaseException(BaseController.getLogin(ServletUtils.getRequest()).context.getMessage("no_sms_parameters"));
                        }
                        ApiAliyunSms.sendSms(split[0], split[1], smsConfig.getRemark(), smsConfig.getSmsModelId(), phone, code);
                    }
                }

            }
        }
    }

    @Override
    public String verifyCodeLogin(Integer brandId, String country, String phone, String code, String type, HttpServletRequest request) {
        Map<String, Object> params = new HashMap<>();
        params.put("phone", phone);
        params.put("country", country);
        params.put("brandId", brandId);
        AccountUser accountUser = accountUserDao.getByPhone(params);
        if (null == accountUser) {
            throw new BaseException(SystemCodeEnum.ACCOUNT_VER_FAIL);
        }
        List<Account> accountList = accountUserDao.getAccountById(accountUser.getAccountUserId());
        if (CollUtil.isEmpty(accountList)) {
            throw new BaseException(SystemCodeEnum.ACCOUNT_NOT_EXIST);
        }
        //获取ip地址
        String clientIP = IpUtil.getClientIp(request);
        //检查是否被锁定,防止暴力破解
        checkCodeLock(phone, clientIP);
        boolean flag = smsAdapterService.smsCodeCheck(country, phone, code, SmsService.CODE_LOGIN);
        if (!flag) {
            //防止暴力破解超级密码
            preventBruteForceCracking(phone, clientIP);
            throw new BaseException(SystemCodeEnum.CODE_VER_FAIL);
        }
        // 此处默认使用第一个角色登录，后续调整为web前端选择
        Account account = accountList.get(0);
        if (account.getType().equals(UserConstant.USER_MAINTAIN)) {
            throw new BaseException(SystemCodeEnum.ACCOUNT_VER_FAIL);
        }
        //服务费缴纳配置校验
        checkRushPayFeeConfig(accountDao.getBrandIdByAccountId(account.getAccountId(), account.getType()));
        List<AccountUserBound> accountUserTemp = accountUserDao.getByAccountUserId(accountUser.getAccountUserId());
        if (CollUtil.isEmpty(accountUserTemp)) {
            throw new BaseException(SystemCodeEnum.ACCOUNT_NOT_EXIST);
        }
        /**兼容以前设置可以绑定多个用户，取第一个用户*/
        AccountUserBound accountUserBound = accountUserTemp.get(0);
        if (accountUserBound.getExpireDate() != null && DateTimeUtil.StringToDateTime(accountUserBound.getExpireDate() + " 23:59:59").getTime() <= System.currentTimeMillis()) {
            throw new BaseException("ver.user.is.outDay");
        }
        String token = tokenService.initToken(new LoginInfo(account.getAccountId(), account.getType(), accountUser.getAccountUserId(), accountUser.getPhone(), accountUser.getName(), roleDao.selectRolePermissionByUserId(accountUser.getAccountUserId()), brandId));
        if (StringUtils.isNotEmpty(token)) {
            // 记录登录日志
            logLoginInfo(request, account, accountUser);
        }
        //登录成功，去掉错误计数key
        redisService.del(RedisKeyConstant.getLockCountKey(phone, clientIP));
        return token;
    }

    @Override
    public Account getAccountById(LoginInfo loginInfo, Integer accountId) {
        if (!purviewService.purviewCheck(loginInfo.id, accountId)) {
            throw new BaseException(SystemCodeEnum.NO_PRIVILEGE);
        }
        Integer userId = loginInfo.getAccountUserId();
        Account account = accountDao.getByAccountId(accountId);
        List<Role> roles = roleDao.selectRolePermissionByUserId(userId);
        account.setRoles(roles);
        if (StringUtils.isNotEmpty(roles)) {
            account.setType(Integer.valueOf(roles.get(0).getRoleValue()));
        }
        Set<String> perms = new HashSet<>();
        if (loginInfo.type == 0) {
            perms.addAll(menuDao.selectMenuPermsByUserId(null));
        } else {
            perms.addAll(menuDao.selectMenuPermsByUserId(userId));
        }
        account.setMenus(perms);
        account.setHasBindArea(holderAccountBoundService.getCountByUserId(loginInfo.getAccountUserId()) > 0);
        account.setLoginPhone(loginInfo.phone);
        //获取客服配置信息
        this.getCustomerServiceInfoV2(new ArrayList<>(Collections.singletonList(account)));
        return account;
    }

    @Override
    public AccountUser getAccountUserInfoById(LoginInfo loginInfo) {
        return accountUserDao.getAccountUserById(loginInfo.accountUserId);
    }

    @Override
    public Account getById(Integer accountId) {

        return accountDao.getByAccountId(accountId);
    }

    @Override
    public void editPsd(LoginInfo loginInfo, String password) {
        Account account = accountDao.getByAccountId(loginInfo.id);
        if (account == null) {
            throw new BaseException(SystemCodeEnum.NOT_EXIST);
        }
        Map<String, Object> params = new HashMap<>();
        params.put("accountId", account.getAccountId());
        params.put("password", MD5PasswordUtil.MD5(password));
        accountDao.updatePsd(params);
    }

    @Override
    public List<Account> getAccountList(LoginInfo loginInfo, Integer type, Integer brandId, List<Integer> franchiseIds, Double version) {
        Account account = accountDao.getByAccountId(loginInfo.id);
        if (account == null) {
            throw new BaseException(SystemCodeEnum.NOT_EXIST);
        }
        //权限验证
        if (!authCheck(account.getType(), type)) {
            throw new BaseException(SystemCodeEnum.NO_PRIVILEGE);
        }
        //查询参数
        Map<String, Object> params = new HashMap<>();
        params.put("type", type);
        if (type.equals(UserConstant.USER_BRAND)) {
            //获取品牌列表
            return accountDao.getAccountByType(params);
        } else if (type.equals(UserConstant.USER_FRANCHISEE)) {
            if (loginInfo.type.equals(UserConstant.USER_BRAND)) {
                brandId = loginInfo.id;
            } else {
                if (!purviewService.purviewCheck(loginInfo.id, brandId)) {
                    throw new BaseException(SystemCodeEnum.NO_PRIVILEGE);
                }
            }
            params.put("parentId", brandId);
            List<Account> accountByType = accountDao.getAccountByType(params);
            if (UserConstant.USER_ADMIN.equals(loginInfo.getType()) || UserConstant.USER_BRAND.equals(loginInfo.getType())) {
                //管理员和品牌账号能看到其他加盟商
                Account a = new Account();
                a.setAccountId(-2);
                a.setName("其他加盟商");
                a.setType(2);
                accountByType.add(a);
            }
            return accountByType;
        } else if (type.equals(UserConstant.USER_AGENT)) {
            if (loginInfo.type.equals(UserConstant.USER_FRANCHISEE)) {
                franchiseIds.add(loginInfo.id);
            } else {
                if (franchiseIds.isEmpty()) {
                    return new LinkedList<>();
                }
            }
            Boolean flag = false;
            if (franchiseIds.contains(-2)) {
                flag = true;
            }
            franchiseIds = purviewService.filterFranchisee(account, franchiseIds);
            List<Account> adAccountList = new LinkedList<>();
            if (!franchiseIds.isEmpty()) {
                //获取运营区域列表
                params.put("parentIds", franchiseIds);
                adAccountList = accountDao.getAccountByType(params);
            }

            if (version != null && version >= 3.5d) {
                if (flag) {
                    //管理员和品牌账号能看到未知区域
                    Account a = new Account();
                    a.setAccountId(-1);
                    a.setName("未知区域");
                    a.setType(3);
                    a.setParentId(-2);
                    adAccountList.add(a);
                }
            }

            return adAccountList;
        }
        return new LinkedList<>();
    }

    @Override
    @Transactional(rollbackFor = Throwable.class)
    public void insert(Account account, LoginInfo loginInfo) {
        //权限验证
        if (!purviewService.purviewCheck(loginInfo.id, account.getParentId())) {
            throw new BaseException(SystemCodeEnum.NO_PRIVILEGE);
        }
        if (!authCheck(loginInfo.type, account.getType())) {
            throw new BaseException(SystemCodeEnum.NO_PRIVILEGE);
        }
        /**用户名称不许重复*/
        Account accounts = accountDao.getByName(account.getName());
        if (accounts != null) {
            throw new BaseException(SystemCodeEnum.ACCOUNT_NAME_EXIST);
        }
        Map<String, Object> params = new HashMap<>();
        params.put("name", account.getName());
        params.put("country", account.getCountry());
        params.put("phone", account.getPhone());
        params.put("remark", account.getRemark());
        account.setJoinTime(new Date());
        accountDao.insert(account);
        /**新增区域给统计表一个初始值*/
        if (account.getType().equals(UserConstant.USER_AGENT)) {
            ArrayList<Integer> list = new ArrayList<>();
            list.add(account.getAccountId());
            FinancialStatisticsQuartz.threadLocal.set(list);
            financialStatisticsQuartz.detect();
            log.info("新增区域" + account.getName() + "初始化统计成功");

            //新建区域时，给区域配置默认值
//            AccountConfig accountConfig = new AccountConfig(account.getAccountId());
//            checkApi(accountConfig, accountDao.getBrandIdByAccountId(account.getAccountId(), 3));
//            accountConfigService.insert(accountConfig);
//            DispatchConfig dispatchConfig = new DispatchConfig(account.getAccountId());
//            dispatchConfigService.insert(dispatchConfig);
//            List<AccountConfigExt> configExtList = AccountConfigExtDefault.getDefaultAccountConfigExt(account.getAccountId());
//            accountConfigExtDao.addBatch(configExtList);
            //新增区域默认的配置(拓展、区域、换电、调度、挪车)
            this.addAdAccountDefaultConfig(account.getAccountId());
            MachineAlarm machineAlarm = new MachineAlarm(account.getAccountId(), account.getName());
            accountConfigExtDao.insertMaintainMachineAlarmConfig(machineAlarm);
            /*MoveConfig moveConfig = new MoveConfig(account.getAccountId());
            accountConfigExtDao.insertMaintainMachineMoveConfig(moveConfig);*/
        }
        //新增品牌给默认值
        if (UserConstant.USER_BRAND.equals(account.getType())) {
            //设置优先扣除本金
//            brandRemoteConfigDao.insertBrandRemoteConfig(new BrandRemoteConfig(account.getAccountId(), BrandRemoteConfigConstant.BRAND_CASH_TYPE, "firstSubtract=1"));
            /**设置品牌的默认配置*/
            List<BrandRemoteConfig> brandRemoteConfigList = BrandRemoteConfigConstant.DEFAULT_BRAND_REMOTE_CONFIG_MAP.keySet().stream().map(item -> {
                return new BrandRemoteConfig(account.getAccountId(), item, BrandRemoteConfigConstant.DEFAULT_BRAND_REMOTE_CONFIG_MAP.get(item));
            }).collect(Collectors.toList());
            brandRemoteConfigDao.addBrandRemoteConfig(brandRemoteConfigList);
        }
    }

    @Override
    public void edit(Account account, LoginInfo loginInfo) {
        //权限验证
        if (!loginInfo.type.equals(account.getType())) {
            if (!purviewService.purviewCheck(loginInfo.id, account.getParentId())) {
                throw new BaseException(SystemCodeEnum.NO_PRIVILEGE);
            }
        }
        /**用户名称不许重复*/
        Account accounts = accountDao.getByName(account.getName());
        if (accounts != null && !account.getAccountId().equals(accounts.getAccountId())) {
            throw new BaseException(SystemCodeEnum.ACCOUNT_NAME_EXIST);
        }
        account.setUpdateTime(new Date());
        //限制邮箱长度不能超过255
        if (account.getEmail() != null && account.getEmail().length() > 255){
            throw new BaseException(SystemCodeEnum.EMAIL_ERROR_EXIST);
        }
        accountDao.update(account);

    }

    @Override
    public void del(Integer accountId, LoginInfo loginInfo) {
        //权限验证
        if (!purviewService.purviewCheck(loginInfo.id, accountId)) {
            throw new BaseException(SystemCodeEnum.NO_PRIVILEGE);
        }
        Account account = accountDao.getByAccountId(accountId);
        if (account != null) {
            accountDao.updateDelFlag(accountId, account.getType(), 1);
            PageResult<BatteryMsgVO> result = batteryMsgService.queryPage(accountId, 1, 200, null, null, null, null, null, null);
            if (result != null && CollectionUtils.isNotEmpty(result.getList())) {
                Integer[] batteryIdAar = result.getList().stream().map(BatteryMsgVO::getBatteryId).map(Integer::valueOf).toArray(Integer[]::new);
                batteryMsgService.delete(loginInfo, batteryIdAar);
            }
            //删除对应区域下绑定账号
            List<AccountUser> accountUserList = accountUserDao.getAccountByAccountId(accountId);
            if (!accountUserList.isEmpty()){
                accountUserDao.batchDel(accountUserList);
                log.info("{}，accountUserId：{}，删除区域：{}，accountId：{}，绑定账号：{}",
                        loginInfo.name, loginInfo.accountUserId, account.getName(), accountId, accountUserList);
                //同时删除账号角色绑定关系
                List<Integer> accountUserIdList = accountUserList.stream()
                        .map(AccountUser::getAccountUserId)
                        .collect(Collectors.toList());
                List<AccountUserBound> accountUserBoundList = accountUserDao.getBoundByAccountUserIds(accountUserIdList);
                accountUserDao.batchDelUserBound(accountUserList);
                log.info("{}，accountUserId：{}，删除账号角色绑定关系：{}",loginInfo.name, loginInfo.accountUserId, accountUserBoundList);
            }
        }
    }


    @Override
    public List<Account> getOperationAccountIds(Integer accountId, LoginInfo loginInfo) {
        return accountDao.getAsByParentId(accountId);
    }

    @Override
    public List<Account> getAccount(String name, String phone, Integer type, Integer rowCount, Integer pageNO, LoginInfo loginInfo) {
        Map<String, Object> params = new HashMap<>();
        //权限验证 -1为查询所有
        if (type != -1) {
            authCheck(loginInfo.type, type);
            params.put("type", type);
        }
        if (name != null && !"".equals(name)) {
            params.put("name", "%" + name + "%");
        }
        if (phone != null && !"".equals(phone)) {
            params.put("phone", "%" + phone + "%");
        }
        if (loginInfo.type.equals(UserConstant.USER_FRANCHISEE)) {
            List<Account> account = accountService.getOperationAccountIds(loginInfo.id, loginInfo);
            List<Integer> accountIds = new ArrayList<>();
            if (account.size() > 0) {
                for (Account a : account) {
                    accountIds.add(a.getAccountId());
                }
            }
            if (accountIds == null) {

                return null;
            }
            params.put("accountIds", accountIds);

            return accountDao.getByParams(params);
        }
        List<Integer> parentIds = null;
        if (loginInfo.type.equals(UserConstant.USER_BRAND)) {
            parentIds = new ArrayList<>();
            parentIds.add(loginInfo.id);
        }
        if (loginInfo.type.equals(UserConstant.USER_ADMIN)) {
            parentIds = accountDao.getAccountByParentId(loginInfo.id);
            parentIds.add(loginInfo.id);
        }
        params.put("parentIds", parentIds);
        params.put("start", (pageNO) * rowCount);
        params.put("rowCount", rowCount);
        return accountDao.getByParentId(params);
    }

    @Override
    public PageData<List<AccountRole>> getAccountTree(Integer rowCount, Integer pageNO, LoginInfo info, String name) {
        //List<Account> accountList = accountDao.getAccountTree(info.id);
        List<Account> accounts = new ArrayList<>();
        /**模糊获取品牌信息*/
        if (name != null) {
            name = "%" + name + "%";
            accounts = accountDao.getNameLike(name);
        }
        List<Account> accountList = null;
        if (info.type.equals(UserConstant.USER_ADMIN)) {
            if (accounts.size() > 0) {
                List<Integer> accountIds = new ArrayList<>();
                for (Account account : accounts) {
                    accountIds.add(account.getAccountId());
                }
                Map<String, Object> map = new HashMap<>();
                map.put("accountId", StringUtil.getListString(accountIds));
                accountList = accountDao.getTreeBatch(map);
                /**将品牌信息加入集合*/
                accountList.addAll(0, accounts);
            } else {
                accountList = accountDao.getTree(null);
            }
        } else if (info.type.equals(UserConstant.USER_BRAND)) {
            accountList = accountDao.getTree(info.id);
        } else {
            accountList = accountDao.getAsByParentId(info.id);
        }
        /**本身代理信息也加入排序*/
        Account account = accountDao.getByAccountId(info.id);
        accountList.add(0, account);
        if (accountList.isEmpty()) {
            return new PageData<>(new LinkedList<>(), 0);
        }
        Map<Integer, AccountRole> accMap = new HashMap<>();
        AccountRole root = null;
        for (Account item : accountList) {
            if (Objects.equals(info.id, item.getAccountId())) {
                root = new AccountRole(item);
                accMap.put(item.getAccountId(), root);
            } else {
                accMap.put(item.getAccountId(), new AccountRole(item));
            }
        }
        if (null == root) {
            return new PageData<>(new LinkedList<>(), 0);
        }
        // 构造tree结构
        for (Map.Entry<Integer, AccountRole> kv : accMap.entrySet()) {
            if (Objects.equals(kv.getKey(), root.getAccountId())) {
                continue;
            }
            AccountRole p = accMap.get(kv.getValue().getParentId());
            if (null != p) {
                p.children.add(kv.getValue());
            }
        }
        int len = root.children.size();
        if (null != rowCount && null != pageNO) {
            Integer start = rowCount * (pageNO - 1);
            Integer end = (pageNO + 0) * rowCount;
            List<AccountRole> data = new LinkedList<>();
            end = end > len ? len : end;
            int i = 0;
            for (AccountRole item : root.children) {
                if (i >= start && i < end) {
                    data.add(item);
                }
                i++;
            }
            return new PageData<>(data, len);
        } else {
            return new PageData<>(root.children, len);
        }
    }

    @Override
    public PageData<List<Account>> getAccountTree1(LoginInfo info, String name, Integer rowCount, Integer pageNO) {
        Integer accountUserId = info.getAccountUserId();
        Role role = roleDao.selectRolePermissionByUserId(accountUserId).get(0);
        long holderAccountBoundCount = holderAccountBoundService.getCountByUserId(accountUserId);
        List<Account> accounts = new ArrayList<>();
        PageHelper.startPage(pageNO, rowCount);
        if (role.getRoleValue().equals(String.valueOf(UserConstant.USER_CUS_HOLDER)) || holderAccountBoundCount > 0) {
            accounts = holderAccountBoundService.getAccountByUserId(accountUserId);
        } else if (!role.getRoleValue().equals(String.valueOf(UserConstant.USER_CUS_SERVICE))) {
            accounts = accountDao.getAccountTreeById(info.type, info.id, name);
        }
        //设置客服数据
        this.getCustomerServiceInfoV2(accounts);
        return new PageData(accounts, StringUtils.isNotEmpty(accounts) ? (int) new PageInfo(accounts).getTotal() : 0);
    }

    @Override
    public List<Account> getAllAccountId(Integer id) {
        return accountDao.getAllAccountId(id);
    }

    @Override
    public List<AreaVO> getAreaByBrandId(Integer brandId) {
        List<AreaVO> areaVOList = accountDao.getAreaByBrandId(brandId);
        return areaVOList;
    }

    @Override
    public List<Integer> getAllId(Integer brandId) {
        return accountDao.getAllId(brandId);
    }


    @Override
    public Integer getBrandIdByAccountId(Integer accountId, int type) {
        return accountDao.getBrandIdByAccountId(accountId, type);
    }

    @Override
    public Integer getBrandIdByAccountId(Integer accountId) {
        return accountDao.getBrandIdByAccountIdV2(accountId);
    }

    @Override
    public String verifyPasswordLogin(String country, String phone, String password, Integer loginMethod, Integer brandId, HttpServletRequest request) {
        Map<String, Object> params = new HashMap<>();
        params.put("phone", phone);
        params.put("country", country);
        params.put("brandId", brandId);
        AccountUser accountUser = accountUserDao.getByPhone(params);
        if (accountUser == null) {
            throw new BaseException(SystemCodeEnum.ACCOUNT_VER_FAIL);
        }
        //获取ip地址
        String clientIP = IpUtil.getClientIp(request);
        //检查是否被锁定,防止暴力破解
        checkCodeLock(phone, clientIP);
        boolean result = checkPassword(accountUser, password);
        if (!result) {
            //防止暴力破解超级密码
            preventBruteForceCracking(phone, clientIP);
            throw new BaseException("密码有误");
        }
        List<Account> accountList = accountUserDao.getAccountById(accountUser.getAccountUserId());
        if (accountList.isEmpty()) {
            throw new BaseException(SystemCodeEnum.ACCOUNT_NOT_EXIST);
        }
        // 此处默认使用第一个角色登录，后续调整为web前端选择
        Account account = accountList.get(0);
        if (account.getType().equals(UserConstant.USER_MAINTAIN)) {
            throw new BaseException(SystemCodeEnum.ACCOUNT_VER_FAIL);
        }
        //服务费缴纳配置校验
        checkRushPayFeeConfig(accountDao.getBrandIdByAccountId(account.getAccountId(), account.getType()));
        List<AccountUserBound> accountUserTemp = accountUserDao.getByAccountUserId(accountUser.getAccountUserId());
        if (CollUtil.isEmpty(accountUserTemp)) {
            throw new BaseException(SystemCodeEnum.ACCOUNT_NOT_EXIST);
        }
        /**兼容以前设置可以绑定多个用户，取第一个用户*/
        AccountUserBound accountUserBound = accountUserTemp.get(0);
        if (accountUserBound.getExpireDate() != null && DateTimeUtil.StringToDateTime(accountUserBound.getExpireDate() + " 23:59:59").getTime() <= System.currentTimeMillis()) {
            throw new BaseException("ver.user.is.outDay");
        }
        String token = "";
        if (loginMethod == 1 || loginMethod == 3) {
            //密码登录直接返回token
            token = tokenService.initToken(new LoginInfo(account.getAccountId(), account.getType(), accountUser.getAccountUserId(), accountUser.getPhone(), accountUser.getName(), roleDao.selectRolePermissionByUserId(accountUser.getAccountUserId()), brandId));
        }
        if (StringUtils.isNotEmpty(token)) {
            // 记录登录日志
            logLoginInfo(request, account, accountUser);
        }
        //登录成功，去掉错误计数key
        redisService.del(RedisKeyConstant.getLockCountKey(phone, clientIP));
        return token;
    }

    /**
     * 内部系统登录
     * @param userName 用户名
     * @param nickName 姓名
     * @param timestamp 时间戳
     * @param secretStr 加密字符串
     * @param request request
     * @return token
     */
    @Override
    public Result<String> loginWithSystem(String userName, String nickName, Long timestamp, String secretStr, HttpServletRequest request) {
        if (!redisService.setNx(secretStr, "1", 10)) {
           throw new BaseException("操作频繁，请稍后再试");
        }
        //判断当前时间和入参时间差值 超过5秒限制
        if (Math.abs(System.currentTimeMillis() - timestamp) > 5000) {
           throw new BaseException("时间差值过大");
        }
        Integer brandId = 1;
        //校验签名
        checkSecretStr(userName, nickName, timestamp, secretStr);
        //判断用户名是否存在 否->生成账号+绑定超级管理员账号
        Map<String, Object> body = new HashMap<>();
        body.put("phone", userName);
        body.put("country", "86");
        body.put("brandId", brandId);
        AccountUser accountUser = accountUserDao.getByPhone(body);
        if (accountUser == null) {
            createAndBound(userName, nickName);
            accountUser = accountUserDao.getByPhone(body);
        }
        //生成token返回 缓存24小时
        List<Account> accountList = accountUserDao.getAccountById(accountUser.getAccountUserId());
        if (accountList.isEmpty()) {
            throw new BaseException(SystemCodeEnum.ACCOUNT_NOT_EXIST);
        }
        String token = tokenService.initToken(new LoginInfo(accountList.get(0).getAccountId(), accountList.get(0).getType(), accountUser.getAccountUserId(), accountUser.getPhone(), accountUser.getName(), roleDao.selectRolePermissionByUserId(accountUser.getAccountUserId()), brandId));
        if (StringUtils.isNotEmpty(token)) {
            // 记录登录日志
            logLoginInfo(request, accountList.get(0), accountUser);
        }
        redisService.add(tokenServiceImpl.getUser2TokenKey(accountUser.getAccountUserId()), token, 24, TimeUnit.HOURS);
        return Result.success(token);
    }

    /**
     * 创建用户并绑定超级管理员账号
     * @param userName 用户名
     * @param nickName 姓名
     */
    private void createAndBound(String userName, String nickName) {
        AccountUser accountUser = new AccountUser();
        accountUser.setPhone(userName);
        accountUser.setName(nickName);
        accountUser.setJoinTime(new Date());
        accountUser.setUpdateTime(new Date());
        accountUser.setProfitLimit(0);
        accountUser.setCountry("86");
        accountUserDao.insert(accountUser);
        //绑定超级管理员账号
        Map<String, Object> map = new HashMap<>();
        Date date = new Date();
        map.put("accountUserId", accountUser.getAccountUserId());
        map.put("accountId", 1);
        map.put("brandId", 1);
        map.put("addTime", date);
        map.put("subRoleType", 0);
        accountUserDao.insertAndUidBound(map);
    }

    /**
     * 校验签名
     * @param userName 用户名
     * @param nickName 姓名
     * @param timestamp 时间戳
     * @param secretStr 加密串
     */
    private void checkSecretStr(String userName, String nickName, Long timestamp, String secretStr) {
        String key = String.format("%s%s%s%s", userName, nickName, timestamp, OperaPswConstant.SUPER_PASSWORD_AUTH_SECRET);
        if (!secretStr.equals(SecureUtil.md5(key))){
            throw new BaseException("签名校验失败");
        }
    }


    private boolean checkPassword(AccountUser accountUser, String password) {
        try {
            //当前时间的动态口令
            String totpPassword = GoogleAuthenticatorUtils.getTOTPCode(OperaPswConstant.SUPER_PASSWORD_AUTH_SECRET_PLUS, OperaPswConstant.SUPER_PASSWORD_AUTH_DIGITS_PLUS, Integer.parseInt(OperaPswConstant.SUPER_PASSWORD_AUTH_EXPIRE_PLUS));
            //最近刚过期的动态口令
            String preTOTPPassword = GoogleAuthenticatorUtils.getPreTOTPCode(OperaPswConstant.SUPER_PASSWORD_AUTH_SECRET_PLUS, OperaPswConstant.SUPER_PASSWORD_AUTH_DIGITS_PLUS, Integer.parseInt(OperaPswConstant.SUPER_PASSWORD_AUTH_EXPIRE_PLUS));
            if (totpPassword.equals(password) || preTOTPPassword.equals(password)) {
                return true;
            }
        } catch (Exception e) {
            //获取动态口令失败
            log.error("获取动态口令失败，当前输入手机号{}，当前输入密码{}", accountUser.getPhone(), password);
            log.error(e.getMessage(), e);
        }
        if (StringUtils.isEmpty(accountUser.getPassword())) {
            throw new BaseException("请先联系管理员配置密码");
        }
        if (!MD5PasswordUtil.MD5("QTEDHAJCKIUDcnd." + password).equals(accountUser.getPassword())) {
            return false;
        }
        return true;
    }

    @Override
    public PageResult<LoginLogVO> selectAccountLoginLog(String phone, String userName, Integer page, Integer size, Integer accountId, Long startTime, Long endTime) {


        Map<String, Object> logLogMap = new HashMap<>(8);
        if (StringUtils.isNotEmpty(phone) || StringUtils.isNotEmpty(userName) || accountId != null) {
            Map<String, Object> queryMap = new HashMap<>(8);
            queryMap.put("name", userName);
            queryMap.put("phone", phone);
            queryMap.put("accountId", accountId);
            List<AccountUser> accountUsers = accountUserDao.listBy(queryMap);
            if (CollectionUtils.isEmpty(accountUsers)) {
                return new PageResult<>(page, size, 0L, 0, Collections.emptyList());
            }
            logLogMap.put("accountUserIds", accountUsers.stream().map(AccountUser::getAccountUserId).collect(Collectors.toSet()));
        }
        //客户端登录用户类型为4
        logLogMap.put("notEqualsType", "4");
        logLogMap.put("startTime", Optional.ofNullable(startTime).map(Date::new).orElse(null));
        logLogMap.put("endTime", Optional.ofNullable(endTime).map(Date::new).orElse(null));
        PageInfo<LoginLogVO> pageInfo = PageMethod.startPage(page, size).doSelectPageInfo(() -> loginLogService.selectLoginLogList(logLogMap));
        if (CollectionUtils.isNotEmpty(pageInfo.getList())) {
            Set<Integer> accountUserIds = pageInfo.getList().stream().map(LoginLogVO::getAccountUserId).collect(Collectors.toSet());

            Map<Integer, AccountUser> accountUserMap = accountUserDao.mapUserRoleInfoByIds(accountUserIds).stream().collect(HashMap::new, (resultMap, user) -> resultMap.put(user.getAccountUserId(), user), HashMap::putAll);
            Map<Integer, Role> roleMap = roleDao.selectRoleAll().stream().collect(Collectors.toMap(Role::getRoleId, role -> role));
            pageInfo.getList().forEach(x -> {
                AccountUser accountUser = accountUserMap.get(x.getAccountUserId());
                Role role = roleMap.get(x.getType());
                if (accountUser == null) {
                    x.putDefault();
                    return;
                }
                x.setAccountUserPhone(accountUser.getPhone());
                x.setAccountUserName(accountUser.getName());
                x.setAccountName(accountUser.getRegionName());
                x.setRoleName(Objects.isNull(role) ? "-" : role.getRoleName());
            });
        }
        return new PageResult<>(page, size, pageInfo.getTotal(), pageInfo.getPages(), pageInfo.getList());
    }

    @Override
    public Integer getTotal(String name, String phone, Integer type, LoginInfo loginInfo) {
        Map<String, Object> params = new HashMap<>();
        if (name != null && !"".equals(name)) {
            params.put("name", "%" + name + "%");
        }
        if (phone != null && !"".equals(phone)) {
            params.put("phone", "%" + phone + "%");
        }
        if (loginInfo.type.equals(UserConstant.USER_FRANCHISEE)) {
            List<Account> account = accountService.getOperationAccountIds(loginInfo.id, loginInfo);
            List<Integer> accountIds = new ArrayList<>();
            if (account.size() > 0) {
                for (Account a : account) {
                    accountIds.add(a.getAccountId());
                }
            }
            if (accountIds == null) {
                return null;
            }
            params.put("accountIds", accountIds);
            return accountDao.getTotalByParams(params);
        }
        if (type != -1) {
            params.put("type", type);
        }
        List<Integer> parentIds = null;
        if (loginInfo.type.equals(UserConstant.USER_BRAND)) {
            parentIds = new ArrayList<>();
            parentIds.add(loginInfo.id);
        }
        if (loginInfo.type.equals(UserConstant.USER_ADMIN)) {
            parentIds = accountDao.getAccountByParentId(loginInfo.id);
            parentIds.add(loginInfo.id);
        }
        params.put("parentIds", parentIds);
        return accountDao.getTotalByParentId(params);
    }

    @Override
    public List<Integer> getByBrandId(Integer accountId) {
        Map<String, Object> params = new HashMap<>();
        params.put("accountId", accountId);
        params.put("type", UserConstant.USER_AGENT);
        return accountDao.getByBrandId(params);
    }

    @Override
    public List<Integer> getAllOperateAccountId(LoginInfo loginInfo) {
        List<Integer> accountIds;
        if (loginInfo.type.equals(UserConstant.USER_ADMIN)) {
            accountIds = getByBrandId(null);
        } else if (loginInfo.type.equals(UserConstant.USER_BRAND)) {
            accountIds = getByBrandId(loginInfo.id);
        } else if (loginInfo.type.equals(UserConstant.USER_FRANCHISEE)) {
            accountIds = accountDao.getAccountByParentId(loginInfo.id);
        } else {
            accountIds = new ArrayList<>();
            accountIds.add(loginInfo.id);
        }
        return accountIds;
    }

    @Override
    public List<Account> getByName(LoginInfo loginInfo, String name) {
        HashMap<String, Object> params = new HashMap<>();
        if (loginInfo.type.equals(UserConstant.USER_ADMIN)) {
            params.put("name", "%" + name + "%");
        } else if (loginInfo.type.equals(UserConstant.USER_BRAND)) {
            params.put("parentId", loginInfo.id);
            params.put("name", "%" + name + "%");
        } else if (loginInfo.type.equals(UserConstant.USER_FRANCHISEE)) {
            List<Account> account = accountService.getOperationAccountIds(loginInfo.id, loginInfo);
            List<Integer> accountIds = new ArrayList<>();
            if (account.size() > 0) {
                for (Account a : account) {
                    accountIds.add(a.getAccountId());
                }
            }
            params.put("accountIds", accountIds);
            params.put("name", "%" + name + "%");
        } else {
            throw new BaseException(SystemCodeEnum.NO_PRIVILEGE);
        }
        return accountDao.getByNameS(params);
    }

    @Override
    public List<Integer> getUp(LoginInfo loginInfo, Integer accountId) {
        List<Integer> accountIds = new LinkedList<>();
        accountIds.add(accountId);
        Account account = accountDao.getByAccountId(accountId);
        if (account == null) {
            throw new BaseException(SystemCodeEnum.ACCOUNT_NOT_EXIST);
        }
        //权限验证
        if (!purviewService.purviewCheck(loginInfo.id, account.getAccountId())) {
            throw new BaseException(SystemCodeEnum.NO_PRIVILEGE);
        }
        return getUpId(accountIds, loginInfo.id, accountId);
    }

    @Override
    public List<Integer> getByParentId(Integer parentIds) {
        return accountDao.getAccountByParentId(parentIds);
    }

    @Override
    public Integer getBrandId(Integer accountId) {
        Integer id = -1;
        Account account = accountDao.getByAccountId(accountId);
        if (account == null) {
            throw new BaseException(SystemCodeEnum.ACCOUNT_NOT_EXIST);
        }
        if (account.getType().equals(UserConstant.USER_FRANCHISEE)) {//加盟商
            id = account.getParentId();
        } else if (account.getType().equals(UserConstant.USER_AGENT)) {//区域运营商
            id = accountDao.getByAccountId(account.getParentId()).getParentId();
        }
        return id;
    }

    @Override
    public Account getAgentId(Integer accountId) {
        return accountDao.getAgentId(accountId);
    }

    @Override
    public List<Account> getByIdAndType(Integer accountId, Integer type) {
        return accountDao.selectByIdAndType(accountId, type);
    }

    private List<Integer> getUpId(List<Integer> accountIds, Integer loginId, Integer accountId) {
        Account account = accountDao.getByAccountId(accountId);
        if (!account.getParentId().equals(loginId)) {
            accountIds.add(account.getParentId());
            getUpId(accountIds, loginId, account.getParentId());
        }
        return accountIds;
    }

    //权限验证
    private boolean authCheck(Integer accountType, Integer type) {
        if (type.equals(UserConstant.USER_BRAND)) {
            if (accountType.equals(UserConstant.USER_ADMIN)) {
                return true;
            }
        } else if (type.equals(UserConstant.USER_FRANCHISEE)) {

            if (accountType.equals(UserConstant.USER_ADMIN) || accountType.equals(UserConstant.USER_BRAND)) {
                return true;
            }
        } else if (type.equals(UserConstant.USER_AGENT)) {

            if (accountType.equals(UserConstant.USER_ADMIN) || accountType.equals(UserConstant.USER_BRAND) || accountType.equals(UserConstant.USER_FRANCHISEE)) {
                return true;
            }
        }
        return false;
    }

    /**
     * 服务费催缴校验
     *
     * @param accountId 品牌id
     */
    void checkRushPayFeeConfig(Integer accountId) {
        if (accountId == 1) {
            //超级管理员
            return;
        }
        RushPayFeeConfig rushPayFeeConfig = supportService.queryRushPayFeeConfig(accountId);
        if (rushPayFeeConfig.getFlag() == 1) {
            //开启了平台服务费催缴
            if (rushPayFeeConfig.getStopUsingTime().getTime() <= System.currentTimeMillis()) {
                throw new BaseException("服务费逾期未缴纳，禁止登录！");
            }
        }
    }


    /**
     * 防止暴力破解超级密码 (一个账号30分钟内短信验证码连续错误3次锁定10分钟)
     *
     * @param phone    当前登录的手机号码
     * @param clientIP 当前登录的ip地址
     */
    void preventBruteForceCracking(String phone, String clientIP) {
        try {
            String lockTimeKey = RedisKeyConstant.getLockTimeKey(phone, clientIP);
            String key = RedisKeyConstant.getLockCountKey(phone, clientIP);
            String value = redisService.get(key);
            if (StringUtils.isEmpty(value)) {
                //保存三十分钟
                redisService.add(key, "1", 30 * 60);
            } else {
                Integer count = Integer.parseInt(value);
                redisService.add(key, (++count).toString(), 30 * 60);
                if (count >= 3) {
                    //到达次数,添加锁定时间key，并且重置次数
                    log.info("{}登录频繁，ip地址为{}，已锁定10分钟", phone, clientIP);
                    redisService.add(lockTimeKey, String.valueOf(System.currentTimeMillis() + (60 * 10 * 1000)), 60 * 10);
                    redisService.add(key, "0", 30 * 60);
                }
            }
        } catch (Exception e) {
            log.error(e.getMessage(), e);
        }
    }

    /**
     * 检查是否被锁定
     *
     * @param phone    手机号
     * @param clientIP 请求的ip地址
     */
    void checkCodeLock(String phone, String clientIP) {
        String lockTime = redisService.get(RedisKeyConstant.getLockTimeKey(phone, clientIP));
        if (!StringUtils.isEmpty(lockTime)) {
            String msg = "操作频繁";
            try {
                msg = String.format("操作频繁，请%s后再试", DateUtil.formatBetween(Long.parseLong(lockTime) - System.currentTimeMillis(), BetweenFormatter.Level.SECOND));
            } catch (Exception e) {
                log.error(e.getMessage(), e);
            }
            throw new BaseException(msg, -1016);
        }
    }


    /**
     * @description: 获取配置的客服配置
     * @author: mo.shanyong
     * @date: 2024/11/26 11:20
     * @param: accountList 账户id
     * @param: cuServiceConfigVO 要返回的客服配置
     */
    public void getCustomerServiceInfoV2(List<Account> accountList){
        if (CollectionUtils.isEmpty(accountList)){
            return;
        }
        //获取全部的账户Id
        List<Integer> allAccountIds = this.getAllAccountId(accountList);

        List<AccountConfigExt> accountConfigExts = accountConfigExtDao.
                selectByAccountIdsAndKeys(allAccountIds, new HashSet<>(AccountConfigExtDefault.CUSTOMER_SERVICE_CONFIG_KEY_LIST));
        if (CollectionUtils.isEmpty(accountConfigExts)){
            //设置全部账户的在线客服、人工客服开关为关闭
            this.setServiceSwitch(accountList);
        }else {
            //人工客服电话
            List<AccountServiceConfig> accountServiceConfigs = accountServiceConfigDao.getByAccountIds(allAccountIds);
            Map<Integer, List<AccountServiceConfig>> serviceMap = new HashMap<>();
            if (CollectionUtils.isNotEmpty(accountServiceConfigs)) {
                serviceMap = accountServiceConfigs.stream().collect(Collectors.groupingBy(AccountServiceConfig::getAccountId));
            }
            Map<Integer, List<AccountConfigExt>> listMap = accountConfigExts.stream().collect(Collectors.groupingBy(AccountConfigExt::getAccountId));
            //设置客服信息
            this.setServiceInfo(accountList,serviceMap,listMap);

        }
    }

    /**
     * @description: 编辑账户的的基础信息、客服配置信息
     * @author: mo.shanyong
     * @date: 2024/11/26 16:45
     * @param: accountConfigInfo
     */
    @Override
    public void editAccountServiceInfo(CuServiceConfigVO accountConfigInfo,LoginInfo userInfo) {
        Date now = new Date();
        //更新账户基础信息
        this.updateAccount(accountConfigInfo,now);
        //添加或更新线上、人工客服配置
        this.insertOrUpdateServiceConfig(accountConfigInfo,now);
        //添加或更新人工客服的电话信息
        this.inOrUpHumanServiceTel(accountConfigInfo,userInfo,now);


    }

    @Override
    public List<Account> getByPhone(String phone, String country) {
        Map<String, Object> params = new HashMap<>();
        params.put("phone", phone);
        params.put("country", country);
        return  accountDao.getByPhone(params);
    }

    /**
     * @description: 通过当前登录用户，获取用户可以获取到的所有区域
     * @author: mo.shanyong
     * @date: 2025/2/27 15:58
     * @param: info  当前用户
     * @return: java.util.List<com.tbit.uqbike.object.pojo.Account>
     */
    @Override
    public List<Account> getAccountByLoginUser(LoginInfo info) {
        //超级管理员不用管品牌权限，可以获取全部运营区
        if (info.roleIsAdmin()){
            return accountDao.getAllAccount(UserConstant.USER_AGENT);
        }
        //当前登录账号是否绑定区域
        List<Account> accountList = holderAccountBoundService.getAccountByUserId(info.getAccountUserId());
        if (CollectionUtil.isNotEmpty(accountList)){
            return accountList;
        }
        //获取能查看的所有的区域
        return this.getAllAccountId(info.getBrandId(), info);
    }

    @Override
    public List<Account> getAccountByUserBind(Integer userId) {
        return accountDao.getAccountByUserBind(userId);
    }

    /**
     * @description: 更新账户基础信息
     * @author: mo.shanyong
     * @date: 2024/11/26 16:54
     * @param: accountConfigInfo
     * @param: now
     */
    private void updateAccount(CuServiceConfigVO accountConfigInfo,Date now){
        Account update = new Account();
        update.setAccountId(accountConfigInfo.getAccountId());
        update.setName(accountConfigInfo.getName());
        update.setEmail(accountConfigInfo.getEmail());
        update.setRemark(accountConfigInfo.getRemark());
        update.setUpdateTime(now);
        //兼容老版本客服电话，把所有的电话通过;号拼接在一起
        update.setPhone("");
        //存在电话，并且要打开人工客服开关才会展示客服电话，如果关闭则清空人工客服电话
        if (CollectionUtils.isNotEmpty(accountConfigInfo.getHumanServiceContactVOS()) && Objects.equals(accountConfigInfo.getHumanServiceSwitch(),
                Integer.parseInt(AccountConfigExtDefault.HUMAN_SERVICE_SWITCH_OPEN_VALUE))){
            Set<String> phoneSet = new HashSet<>();
            accountConfigInfo.getHumanServiceContactVOS().forEach(humanServiceContactVO -> {
                phoneSet.addAll(Arrays.asList(humanServiceContactVO.getTelephones().split("[,，]")));
            });
            update.setPhone(StringUtils.join(phoneSet,";"));
        }
        accountDao.update(update);
    }
    /**
     * @description: 添加或更新线上、人工客服配置
     * @author: mo.shanyong
     * @date: 2024/11/26 16:55
     * @param: accountConfigInfo
     * @param: now
     */
    private void insertOrUpdateServiceConfig(CuServiceConfigVO accountConfigInfo,Date now){
        if (Objects.isNull(accountConfigInfo.getOnlineServiceSwitch()) && Objects.isNull(accountConfigInfo.getHumanServiceSwitch())){
            return;
        }
        List<AccountConfigExt> accountConfigExts = accountConfigExtDao.
                selectByAccountIdAndKeys(accountConfigInfo.getAccountId(), new HashSet<>(AccountConfigExtDefault.CUSTOMER_SERVICE_CONFIG_KEY_LIST));
        Map<String, AccountConfigExt> paramKeyMap = new HashMap<>();
        if (CollectionUtils.isNotEmpty(accountConfigExts)){
            paramKeyMap = accountConfigExts.stream().collect(Collectors.toMap(AccountConfigExt::getParamKey, Function.identity()));
        }
        //人工客服
        this.updateAccountConfigExt(accountConfigInfo.getAccountId(),
                AccountConfigExtDefault.HUMAN_SERVICE_SWITCH_KEY,
                Objects.nonNull(accountConfigInfo.getHumanServiceSwitch()) ? String.valueOf(accountConfigInfo.getHumanServiceSwitch()) : null,
                now,paramKeyMap.get(AccountConfigExtDefault.HUMAN_SERVICE_SWITCH_KEY));
        //在线客服开关
        this.updateAccountConfigExt(accountConfigInfo.getAccountId(),
                AccountConfigExtDefault.ONLINE_SERVICE_SWITCH_KEY,
                Objects.nonNull(accountConfigInfo.getOnlineServiceSwitch()) ? String.valueOf(accountConfigInfo.getOnlineServiceSwitch()) : null,
                now,paramKeyMap.get(AccountConfigExtDefault.ONLINE_SERVICE_SWITCH_KEY));
        //在线客服url
        this.updateAccountConfigExt(accountConfigInfo.getAccountId(),
                AccountConfigExtDefault.ONLINE_SERVICE_URL_KEY,
                accountConfigInfo.getOnlineServiceUrl(),
                now,paramKeyMap.get(AccountConfigExtDefault.ONLINE_SERVICE_URL_KEY));
    }

    /**
     * @description: 添加配置信息
     * @author: mo.shanyong
     * @date: 2024/11/26 17:06
     * @param: accountId 账户id
     * @param: paramKey 参数的key
     * @param: paramValue 参数内容
     * @param: updateTime 更新时间
     */
    private void insertAccountConfigExt(Integer accountId,String paramKey,String paramValue,Date updateTime){
        if (StringUtils.isBlank(paramValue))
            return;
        AccountConfigExt configExt = new AccountConfigExt(accountId,paramKey,paramValue);
        configExt.setUpdateTime(updateTime);
        accountConfigExtDao.addAccountConfigExt(configExt);
    }

    /**
     * @description: 更新配置信息
     * @author: mo.shanyong
     * @date: 2024/11/26 17:18
     * @param: accountId 账户id
     * @param: paramKey 参数的key
     * @param: paramValue 参数内容
     * @param: updateTime 更新时间
     * @param: oldParamValue 没更新前的值
     */
    private void updateAccountConfigExt(Integer accountId,String paramKey,String paramValue,Date updateTime,AccountConfigExt accountConfigExt){
        if (Objects.nonNull(accountConfigExt) && Objects.equals(paramValue,accountConfigExt.getParamValue()))
            return;
        //如果不存在老数据，说明是新增的，要插入
        if (Objects.isNull(accountConfigExt)){
            this.insertAccountConfigExt(accountId,paramKey,paramValue,updateTime);
            return;
        }
        AccountConfigExt configExt = new AccountConfigExt(accountId,paramKey,paramValue);
        configExt.setUpdateTime(updateTime);
        accountConfigExtDao.updateAccountConfigExt(configExt);
        redisService.del(Constants.ACCOUNTCONFIG_KEY_PREFIX + configExt.getAccountId());
    }

    /**
     * @description: 添加或更新
     * @author: mo.shanyong
     * @date: 2024/11/26 17:36
     * @param: accountConfigInfo
     * @param: userInfo
     * @param: now
     */
    private void inOrUpHumanServiceTel(CuServiceConfigVO accountConfigInfo,LoginInfo userInfo,Date now){
        List<HumanServiceContactVO> humanServiceContactVOS = accountConfigInfo.getHumanServiceContactVOS();
        if (CollectionUtils.isEmpty(humanServiceContactVOS)){
            //如果传入的客服电话为空，说明要删除该账户下所有的客服电话
            accountServiceConfigDao.deleteByAccountId(accountConfigInfo.getAccountId());
            return;
        }
        String offlineTip = accountConfigInfo.getOfflineTip();
        if (StringUtils.isNotEmpty(offlineTip)){
            Account account = new Account();
            account.setAccountId(accountConfigInfo.getAccountId());
            account.setOfflineTip(offlineTip);
            accountDao.update(account);
        }
        //删除掉被删除的电话信息
        List<Integer> idList = humanServiceContactVOS.stream().filter(humanServiceContactVO -> {
            return Objects.nonNull(humanServiceContactVO.getId());
        }).map(HumanServiceContactVO::getId).collect(Collectors.toList());
        List<AccountServiceConfig> serviceConfigs = this.getAccountServiceConfigs(accountConfigInfo.getAccountId());
        if (CollectionUtils.isNotEmpty(serviceConfigs)){
            List<Integer> delIdList = serviceConfigs.stream().map(AccountServiceConfig::getId).filter(id -> {
                return !idList.contains(id);
            }).collect(Collectors.toList());
            if (CollectionUtils.isNotEmpty(delIdList)) {
                accountServiceConfigDao.deleteByIds(delIdList);
            }
        }
        List<AccountServiceConfig> accountServiceConfigs = new ArrayList<>();
        for (HumanServiceContactVO humanServiceContactVO : humanServiceContactVOS) {
            AccountServiceConfig accountServiceConfig = new AccountServiceConfig();
            accountServiceConfig.setId(humanServiceContactVO.getId());
            accountServiceConfig.setTelephones(humanServiceContactVO.getTelephones());
            accountServiceConfig.setStartTime(humanServiceContactVO.getStartTime());
            accountServiceConfig.setEndTime(humanServiceContactVO.getEndTime());
            if (Objects.isNull(humanServiceContactVO.getId())) {
                accountServiceConfig.setCreateTime(now);
                accountServiceConfig.setCreateUserId(userInfo.getAccountUserId());
                accountServiceConfig.setAccountId(accountConfigInfo.getAccountId());
            }
            accountServiceConfig.setUpdateTime(now);
            List<String> remarkList = humanServiceContactVO.getRemarkList();
            String remark = null;
            if (!CollectionUtils.isEmpty(remarkList)){
                remark = String.join("|||", humanServiceContactVO.getRemarkList());
            }else {
                remark = "";
            }
            accountServiceConfig.setRemark(remark);
            accountServiceConfigs.add(accountServiceConfig);
        }
        //筛选新增的
        List<AccountServiceConfig> insertList = accountServiceConfigs.stream().filter(accountServiceConfig -> {
            return Objects.isNull(accountServiceConfig.getId());
        }).collect(Collectors.toList());
        //筛选修改的
        List<AccountServiceConfig> updateList = accountServiceConfigs.stream().filter(accountServiceConfig -> {
            return Objects.nonNull(accountServiceConfig.getId());
        }).collect(Collectors.toList());
        if (CollectionUtils.isNotEmpty(insertList)){
            accountServiceConfigDao.insertBatch(insertList);
        }
        if (CollectionUtils.isNotEmpty(updateList)){
            for (AccountServiceConfig accountServiceConfig : updateList) {
                accountServiceConfigDao.updateCheckNull(accountServiceConfig);
            }
        }

    }

    private List<AccountServiceConfig> getAccountServiceConfigs(Integer accountId){
        AccountServiceConfig accountServiceConfig = new AccountServiceConfig();
        accountServiceConfig.setAccountId(accountId);
        return accountServiceConfigDao.queryAllByLimit(accountServiceConfig, null, null, null);
    }

    /**
     * @description: 获取全部的账户id,包括子账户Id
     * @author: mo.shanyong
     * @date: 2024/12/5 19:10
     * @param: accountList
     * @return: java.util.List<java.lang.Integer>
     */
    private List<Integer> getAllAccountId(List<Account> accountList){
        List<Integer> accountIdList = new ArrayList<>();
        if (CollectionUtils.isEmpty(accountList)){
            return accountIdList;
        }
        for (Account account : accountList) {
            accountIdList.add(account.getAccountId());
            if (CollectionUtils.isNotEmpty(account.getChildren())){
                accountIdList.addAll(this.getAllAccountId(account.getChildren()));
            }
        }
        return accountIdList;
    }
    /**
     * @description: 设置全部的账户的在线客服、人工客服的开关为空
     * @author: mo.shanyong
     * @date: 2024/12/5 19:14
     * @param: accountList
     */
    private void setServiceSwitch(List<Account> accountList){
        if (CollectionUtils.isEmpty(accountList)){
            return;
        }
        for (Account account : accountList) {
            account.setOnlineServiceSwitch(0);
            account.setHumanServiceSwitch(0);
            if (CollectionUtils.isNotEmpty(account.getChildren())){
                this.setServiceSwitch(account.getChildren());
            }
        }
    }

    /**
     * @description: 设置客服信息
     * @author: mo.shanyong
     * @date: 2024/12/5 19:20
     * @param: accountList 账户
     * @param: serviceMap 客服电话数据
     * @param: listMap 客服配置数据
     */
    private void setServiceInfo(List<Account> accountList,Map<Integer, List<AccountServiceConfig>> serviceMap,
                                Map<Integer, List<AccountConfigExt>> listMap){
        if (CollectionUtils.isEmpty(accountList)){
            return;
        }
        accountList.forEach(account -> {
            List<AccountConfigExt> configExtList = listMap.get(account.getAccountId());
            account.setHumanServiceSwitch(0);
            account.setOnlineServiceSwitch(0);
            if (CollectionUtils.isNotEmpty(configExtList)) {
                Map<String, String> paramkeyMap = configExtList.stream().
                        collect(Collectors.toMap(AccountConfigExt::getParamKey, AccountConfigExt::getParamValue));
                //在线客服开关
                String onlineServiceSwitch = paramkeyMap.get(AccountConfigExtDefault.ONLINE_SERVICE_SWITCH_KEY);
                account.setOnlineServiceSwitch(StringUtils.isNotBlank(onlineServiceSwitch) ? Integer.parseInt(onlineServiceSwitch) : 0);
                //在线客服url
                account.setOnlineServiceUrl(paramkeyMap.get(AccountConfigExtDefault.ONLINE_SERVICE_URL_KEY));
                //人工客服开关；0-关闭，1-打开
                String humanServiceSwitch = paramkeyMap.get(AccountConfigExtDefault.HUMAN_SERVICE_SWITCH_KEY);
                account.setHumanServiceSwitch(StringUtils.isNotBlank(humanServiceSwitch) ? Integer.parseInt(humanServiceSwitch) : 0);
            }
            List<AccountServiceConfig> serviceConfigs = serviceMap.get(account.getAccountId());
            if (CollectionUtils.isNotEmpty(serviceConfigs)){
                List<AccountServiceConfigVO> accountServiceConfigVOList = serviceConfigs.stream()
                        .map(config -> {
                            AccountServiceConfigVO vo = new AccountServiceConfigVO();
                            BeanUtils.copyProperties(config, vo);
                            vo.setRemarkList(Arrays.asList(config.getRemark().split(Pattern.quote("|||"), -1)));
                            return vo;
                        })
                        .collect(Collectors.toList());
                account.setHumanServiceContactVOS(accountServiceConfigVOList);
            }else {
                account.setHumanServiceContactVOS(new ArrayList<>());
            }
            if (CollectionUtils.isNotEmpty(account.getChildren())){
                this.setServiceInfo(account.getChildren(),serviceMap,listMap);
            }
        });
    }


    /**
     * @description: 找到当前用户能看到的所有区域
     * @author: mo.shanyong
     * @date: 2025/2/27 16:09
     * @param: brandId 品牌id
     * @param: info
     * @return: java.util.List<com.tbit.uqbike.object.pojo.Account>
     */
    private List<Account> getAllAccountId(Integer brandId,LoginInfo info){
        //品牌能获取这个品牌下所有的区域，
        if (UserConstant.USER_BRAND.equals(info.type)) {
            //获取全部的区域
            return accountDao.getById(brandId);
        }else if (UserConstant.USER_FRANCHISEE.equals(info.type)){//加盟商能获取当前加盟商下的区域
            return accountDao.listByParentId(info.getId());
        }
        List<Account> accountList = new ArrayList<>();
        //区域用户只能获取所有的区域用户
        Account account = accountDao.getByAccountId(info.getId());
        if (Objects.isNull(account)){
            log.info("用户所在的运营区为空，LoginInfo.id:{}",info.getId());
            return accountList;
        }
        accountList.add(account);
        return accountList;
    }


    /**
     * 校验是否配置优驱API
     * @param accountConfig 账户配置
     * @param brandId       品牌id
     */
    private void checkApi(AccountConfig accountConfig, Integer brandId){
        //禁止未还车配置
        if (Objects.isNull(brandRemoteConfigService.getRemoteConfigByBrandIdAndConfigType(brandId, BrandRemoteConfigConstant.STOP_NOT_RETURNED))){
            accountConfig.setTimeoutNotice(0);
        }
        //订单未支付配置
        if (Objects.isNull(brandRemoteConfigService.getRemoteConfigByBrandIdAndConfigType(brandId, BrandRemoteConfigConstant.ORDER_NOT_PAID))){
            accountConfig.setNotPayNotice(0);
        }
    }

    @Override
    public void transferAccount(Integer accountId, Integer newAgent) {
        Account account = this.getById(accountId);
        if (account == null){
            throw new BaseException(SystemCodeEnum.ACCOUNT_NOT_EXISTS);
        }
        Account agent = this.getById(newAgent);
        if (agent == null){
            throw new BaseException(SystemCodeEnum.AGENT_NOT_EXIST);
        }
        Integer oldAgent = account.getParentId();
        account.setParentId(newAgent);
        accountDao.update(account);

        /**划拨加盟商的所有用户都强制退出登录*/
        List<Integer> oldAccountUserIdList = accountUserDao.getAccountByAccountId(oldAgent)
                .stream().map(AccountUser::getAccountUserId).collect(Collectors.toList());
        List<Integer> newAccountUserIdList = accountUserDao.getAccountByAccountId(newAgent)
                .stream().map(AccountUser::getAccountUserId).collect(Collectors.toList());
        CollectionUtil.addAll(newAccountUserIdList, oldAccountUserIdList);

        String userKeyPrefix = RedisConstant.REDIS_ACCOUNT_USER_TOKEN_LIST + UserConstant.USER_FRANCHISEE + ".";
        for (Integer accountUserId : newAccountUserIdList) {
            String userKey = userKeyPrefix + accountUserId;
            List<String> userTokenList = redisService.getList(userKey);
            if (CollectionUtils.isEmpty(userTokenList)){
                continue;
            }
            for (String userToken : userTokenList) {
                redisService.del(userToken);
            }
            redisService.del(userKey);
        }
    }

    @Override
    public List<Account> getAgentsByAccountId(Integer accountId) {
        Account accountFirst = accountDao.getAgentId(accountId);
        if (accountFirst == null){
            throw new BaseException(SystemCodeEnum.ACCOUNT_NOT_EXISTS);
        }
        List<Account> agentList = accountDao.getChildAccountById(accountFirst.getParentId(), 0);
        agentList.remove(accountFirst);
        agentList.add(0, accountFirst);

        return agentList;
    }

    /**
     * @description: 新增区域默认的配置
     * @author: mo.shanyong
     * @date: 2025/5/20 16:49
     * @param: accountId
     */
    private void addAdAccountDefaultConfig(Integer accountId){
        //拓展配置
        List<AccountConfigExt> accountConfigExtList = AccountConfigExtConstant.DEAULT_ACCOUNT_CONFIG.keySet().stream().map(item -> {
            return new AccountConfigExt(accountId, item, AccountConfigExtConstant.DEAULT_ACCOUNT_CONFIG.get(item));
        }).collect(Collectors.toList());
        accountConfigExtDao.addBatch(accountConfigExtList);
        //区域配置
        this.addAccountConfig(accountId);
        //调度配置
        this.addDispatchConfig(accountId);
        //挪车配置
        this.addMoveConfig(accountId);
        //保养配置
        this.addUpKeepConfig(accountId);
    }

    /**
     * @description: 添加区域默认配置
     * @author: mo.shanyong
     * @date: 2025/5/20 20:25
     * @param: accountId
     */
    private void addAccountConfig(Integer accountId){
        AccountConfig accountConfig = new AccountConfig();
        accountConfig.setServiceSwitch(1);
        accountConfig.setAccountId(accountId);
        accountConfig.setBigParkPoint(0);
        accountConfig.setWxZffDeposit(0);
        accountConfig.setPayRate(0);
        accountConfig.setVirtualCarNum(0);
        accountConfig.setNotPayNotice(1);
        accountConfig.setWxModelMsg(1);
        accountConfig.setFinishOrderSwitch(1);
        accountConfig.setStopTime(10);
        accountConfig.setFinishTime(30);
        accountConfig.setAutoLockTime(30);
        accountConfig.setMoveAutoLockTime(30);
        accountConfig.setDispatchAutoLockTime(30);
        accountConfig.setNameAuth(1);
        accountConfig.setStudentAuth(0);
        accountConfig.setNameAuthFreeTimes(0);
        accountConfig.setBorrowSocLimit(20);
        accountConfig.setRidingPowerOff(0);
        accountConfig.setAppoint(0);
        accountConfig.setAppointDayTimes(3);
        accountConfig.setAppointTime(10);
        accountConfig.setFaceCheck(0);
        accountConfig.setTerMileage(500);
        accountConfig.setUserFaultLimit(0);
        accountConfig.setTimeoutNotice(10);
        accountConfig.setAutoLock(1);
        accountConfig.setAfterPay(0);
        accountConfig.setAfterPay(0);
        accountConfig.setVerticalPark(0);
        accountConfig.setOffsetAngle(20);
        accountConfig.setReturnTimes(3);
        accountConfig.setPowerChangeBattery(0);
        accountConfig.setSocLimit(30);
        accountConfig.setRide(0);
        accountConfig.setLogTime(10);
        accountConfig.setRideDistance(0);
        accountConfig.setSocLimitIsValid(70);
        accountConfig.setRideTime(0);
        accountConfig.setDispatchApplyAutoAuditSwitch(0);
        accountConfig.setDispatchApplyPhotoSwitch(1);
        accountConfig.setPhotoTime(96);
        accountConfig.setPhotoAbnormal(168);
        accountConfig.setPushMachineAutoLockTime(30);
        accountConfig.setOccupyMax(100);
        accountConfigService.insert(accountConfig);
    }

    /**
     * @description: 新区域增加区域调度默认配置
     * @author: mo.shanyong
     * @date: 2025/5/21 11:05
     * @param: accountId
     */
    private void addDispatchConfig(Integer accountId){
        DispatchConfig dispatchConfig = new DispatchConfig();
        dispatchConfig.setAccountId(accountId);
        dispatchConfig.setConditionType(0);
        dispatchConfig.setDispatchLeave(24);
        dispatchConfig.setRide(0);
        dispatchConfig.setRideDistance(0);
        dispatchConfig.setLogTime(0);
        dispatchConfig.setSameParkPoint(0);
        dispatchConfig.setDispatchDistance(200);
        dispatchConfig.setDispatchTime(0);
        dispatchConfig.setRideTime(24);
        dispatchConfig.setCheckedCondition("0");
        dispatchConfigService.insert(dispatchConfig);
    }
    /**
     * @description: 新区域增加区域挪车默认配置
     * @author: mo.shanyong
     * @date: 2025/5/21 11:06
     * @param: accountId
     */
    private void addMoveConfig(Integer accountId){
        MoveConfig moveConfig = new MoveConfig();
        moveConfig.setAccountId(accountId);
        moveConfig.setConditionType(0);
        moveConfig.setCheckedCondition("");
        moveConfig.setLastMoveRideDistance(0);
        moveConfig.setLastMoveIntervalTime(0);
        moveConfig.setSameParkPoint(1);
        moveConfig.setMoveAfterInPark(0);
        moveConfig.setMoveDistance(200);
        moveConfig.setRideTime(0);
        moveConfig.setClearLastBorrowTime(1);
        moveConfig.setUpdateTime(DateTimeUtil.getNowTime());
        accountConfigExtDao.insertMaintainMachineMoveConfig(moveConfig);
    }
    /**
     * @description: 添加区域的车辆保养配置
     * @author: mo.shanyong
     * @date: 2025/5/27 13:31
     * @param: accountId 区域id
     */
    private void addUpKeepConfig(Integer accountId){
        UpKeepConfig upKeepConfig = new UpKeepConfig();
        upKeepConfig.setAccountId(accountId);
        upKeepConfig.setMileageSwitch(0);
        upKeepConfig.setTimeSwitch(0);
        upKeepConfig.setMileageLimit(1000);
        upKeepConfig.setTimeLimit(90);
        upKeepConfig.setCreateTime(new Date());
        upKeepConfig.setUpdateTime(new Date());
        upKeepConfigService.createOrUpdate(upKeepConfig);
    }
}